const webpack = require('webpack');
const fs = require('fs-extra');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
const TerserPlugin = require("terser-webpack-plugin")
const postcssNormalize = require('postcss-normalize')
const paths = require('./paths')
const devSever = require('./webpack.server')
let port = process.env.PORT || 9000
let isPro = process.env.NODE_ENV === 'production'
const copyPublicFolder=() =>{
  fs.copySync(paths.appPublic, paths.appBuild, {
    dereference: true,
    filter: file => file !== paths.appHtml,
  })
  return null
}
const getStyleLoaders = (isEnvProduction,cssOptions,preProcessor)=>{
  const loaders = [
    !isEnvProduction && require.resolve('style-loader'), // 开发环境配置项，把css合并写入到head中
    isEnvProduction && {
      loader: MiniCssExtractPlugin.loader,
      options: {},
    },
    {
      loader: 'css-loader',
      options: cssOptions
    },
    {
      loader: require.resolve('postcss-loader'),
      options: {
        postcssOptions:{
          plugins:[
            require('postcss-flexbugs-fixes'),
            // require('autoprefixer'),
            require('postcss-preset-env')({
              autoprefixer: {
                flexbox: 'no-2009',
              },
              stage: 3,
            }),
            // require('postcss-px-to-viewport-8-plugin')({
            //   viewportWidth: 750/2,
            //   viewportHeight: 1366/2,
            //   unitPrecision: 6,
            //   viewportUnit: 'vw',
            //   selectorBlackList: [],
            //   minPixelValue: 1,
            //   mediaQuery: false
            // }),
            postcssNormalize(),
          ].filter(Boolean)
        }
      },
    }
  ].filter(Boolean)
  if(preProcessor){
    loaders.push({
      loader: require.resolve('resolve-url-loader'),
      options: {
        sourceMap: isEnvProduction,
        // root: paths.appSrc,
      },
    },{
      loader: require.resolve(preProcessor),
      options: {
        sourceMap: true,
      },
    })
  }
  return loaders
}
const getConfigs = (isEnvProduction)=>{
  if(isEnvProduction){
    // 
    fs.emptyDirSync(paths.appBuild);
    // Merge with the public folder
    copyPublicFolder();
  }
  return {
    mode: isEnvProduction ? 'production' : 'development',
    entry:paths.buildEntryConfig(isEnvProduction),
    output:{
      // The build folder.
      path: isEnvProduction ? paths.appBuild : undefined,
      // Add /* filename */ comments to generated require()s in the output.
      pathinfo: !isEnvProduction,
      // There will be one main bundle, and one file per asynchronous chunk.
      // In development, it does not produce real files.
      // filename: isEnvProduction
      //   ? 'static/js/[name].[contenthash:8].js'
      //   : isEnvDevelopment && 'static/js/bundle.js',
      filename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].js'
        : 'static/js/[name].bundle.js',
      // TODO: remove this when upgrading to webpack 5
      // futureEmitAssets: true,
      // There are also additional JS chunk files if you use code splitting.
      chunkFilename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].chunk.js'
        : 'static/js/[name].chunk.js',
      // We inferred the "public path" (such as / or /my-project) from homepage.
      // We use "/" in development.
      publicPath: '/',
    },
    resolve:{
      modules:['node_modules'],
      extensions:['.js','.json'],
      alias:{
        '@':paths.resolveApp('src'),
        '@css':paths.resolveApp('src/css'),
        '@utils':paths.resolveApp('src/utils'),
        '@useHooks':paths.resolveApp('src/useHooks'),
        '@contants':paths.resolveApp('src/contants'),
        '@context':paths.resolveApp('src/context'),
        '@modules':paths.resolveApp('src/modules'),
        '@images':paths.resolveApp('src/images'),
      }
    },
    optimization: {
      minimize: isEnvProduction,
      minimizer: [
        // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
        // `...`,
        new TerserPlugin({
          parallel: true, // 可省略，默认开启并行
          terserOptions: {
              toplevel: true, // 最高级别，删除无用代码
              ie8: true,
              safari10: true,
          }
        }),
        new CssMinimizerPlugin(),
      ],
      // minimizer: [new UglifyJsPlugin()],
      splitChunks: {
        chunks: 'all',
        name: false,
      },
      concatenateModules:false,
      // concatenateModules
      // Keep the runtime chunk separated to enable long term caching
      // https://twitter.com/wSokra/status/969679223278505985
      // https://github.com/facebook/create-react-app/issues/5358
      runtimeChunk: {
        name: entrypoint => `runtime-${entrypoint.name}`,
      },
    },
    devServer: devSever.getDevServer(isEnvProduction,port),
    module: {
      rules: [ 
        {
          test:/\.css$/,
          use:getStyleLoaders(isEnvProduction,{
            importLoaders: 1,
            sourceMap: isEnvProduction ,
          })
        }, 
        {
          test: /\.(scss|sass)$/,
          // exclude: sassModuleRegex,
          use:getStyleLoaders(isEnvProduction,{
            importLoaders: 2,
            modules:{
              localIdentContext:paths.appSrc,
              localIdentName: isEnvProduction?"[hash:base64:12]":"[path][name]--[hash:base64:12]",
              exportLocalsConvention: "camelCase",
            },
            sourceMap: isEnvProduction ,
          },'sass-loader')
        },
        {
          test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
          use:[
            {
              loader: require.resolve('url-loader'),
              options: {
                // 安装url-loader的同时还需要安装file-loader
                // 文件大于limit配置时，file-loader处理文件
                // Webpack file-loader outputs [object Module]
                // 
                esModule: false, // default true
                limit: 1024,
                name: 'static/media/[name].[hash:8].[ext]',
              },
            }
          ]
        }, 
        {
          test: /\.(js|mjs|jsx|ts|tsx)$/,
          exclude: /(node_modules|bower_components)/,
          use:[
            {
              loader: 'babel-loader',
              // options: {
              //   presets: ['@babel/preset-env']
              // }
              options: {
                presets: ['@babel/preset-env'],
                // customize: require.resolve(
                //   'babel-preset-react-app/webpack-overrides'
                // ),
                // This is a feature of `babel-loader` for webpack (not Babel itself).
                // It enables caching results in ./node_modules/.cache/babel-loader/
                // directory for faster rebuilds.
                cacheDirectory: true,
                // See #6846 for context on why cacheCompression is disabled
                cacheCompression: false,
                compact: isEnvProduction,
              },
            }
          ]
        },
      ]
    },
    plugins:[
      new webpack.DefinePlugin({
        'process.env':JSON.stringify({
          NODE_ENV: process.env.NODE_ENV || 'development',
          REACT_APP_ENV:process.env.REACT_APP_ENV
        })
      }),
      !isEnvProduction && new webpack.HotModuleReplacementPlugin(),
      ...paths.appPages.map(item=>{
        return new HtmlWebpackPlugin(
          Object.assign(
            {},
            {
              inject: true,
              template: paths.appHtml,
              // filename:`${item}/index.html`,
              filename:`${item}.html`,
              chunks:[item]
            },
            isEnvProduction
              ? {
                  minify: {
                    removeComments: true,
                    collapseWhitespace: true,
                    removeRedundantAttributes: true,
                    useShortDoctype: true,
                    removeEmptyAttributes: true,
                    removeStyleLinkTypeAttributes: true,
                    keepClosingSlash: true,
                    minifyJS: true,
                    minifyCSS: true,
                    minifyURLs: true,
                  },
                }
              : undefined
          )
        )
      }),
      
      isEnvProduction &&
        new MiniCssExtractPlugin({
          // Options similar to the same options in webpackOptions.output
          // both options are optional
          ignoreOrder:true,
          filename: 'static/css/[name].[contenthash:8].css',
          chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
        }),
      // 忽略 moment 的本地化内容
      // moment 2.18 会将所有本地化内容和核心功能一起打包（见该 GitHub issue）。你可使用 IgnorePlugin 在打包时忽略本地化内容
      // https://github.com/moment/moment/issues/2373
      // webpack 5.v版本写法
      new webpack.IgnorePlugin({
        resourceRegExp: /^\.\/locale$/,
        contextRegExp: /moment/,
      }),
      new webpack.optimize.ModuleConcatenationPlugin()
      // webpack 4.v版本写法
      // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
      // new UglifyJsPlugin()
    ].filter(Boolean)
  }
}

module.exports=getConfigs(isPro)